from math import ceil
from pathlib import Path
import numpy as np
import pandas as pd
import csv

from osc05.static.constants import Constants

import csv
import re
from typing import Tuple


def _parse_float_list(cell: str) -> list[float]:
    """解析单个浮点数或数组字符串为 float 列表"""
    cell = cell.strip().strip('"')  # 去掉外层引号
    if cell.startswith("[") and cell.endswith("]"):
        numbers = re.split(r"[\s,]+", cell[1:-1].strip())
        return [float(x) for x in numbers if x]
    else:
        return [float(cell)]

# 因csv中的布尔型数据的存贮格式发生了变化（逗号+空格分隔），故修改程序
def _parse_bool_list(cell: str) -> list[bool]:
    """解析 numpy 风格的布尔数组字符串为 bool 列表"""
    cell = cell.strip().strip('"')
    if cell.startswith("[") and cell.endswith("]"):
        # 支持逗号和空格分隔（与 float 解析一致）
        tokens = re.split(r"[\s,]+", cell[1:-1].strip())
        # 过滤空字符串，并检查是否为合法布尔字符串
        return [t == "True" for t in tokens if t in ("True", "False")]
    else:
        return [cell in ("1", "True", "true")]

class RandomUtil:
    """Utility class for generating reproducible random sequences."""

    def __init__(self, seed=1, samples_dir=None, n_sf=Constants.N_ACTIVITY):
        self._rng = np.random.default_rng(seed)
        self.n_sf = n_sf
        # new solution
        self.samples_dir = Path(samples_dir) if samples_dir else Path(".")
        self.file_readers = {}  # 存储每个文件的数据迭代器
        self._initialize_file_readers()

        # LHS采样结果文件路径
        self.lhs_file = Path(__file__).resolve().parents[1] / "sampling/lhs/lhs_sampling_results.csv"

        # 打开CSV并创建迭代器
        self._lhs_iter = self._init_lhs_iterator()

    def _initialize_file_readers(self):
        # 这里原本可能有你的文件reader初始化逻辑
        pass

    def _init_lhs_iterator(self):
        """初始化CSV文件迭代器（跳过表头）。"""
        f = open(self.lhs_file, newline='', encoding="utf-8")
        reader = csv.reader(f)
        next(reader, None)  # 跳过表头
        return reader

    def get_samples(
        self, reset: bool = False
    ) -> Tuple[list[float], list[float], list[float], list[bool], list[bool]]:
        """
        从lhs_sampling_results.csv读取一行，并解析为指定的五部分:
        smp_durations: 18列 (float)
        smp_delivery_delay_days: 18列 (float)
        smp_crane_failure_times: 1列 (float)
        smp_rain_hold_daily_events: 1列 (bool)
        smp_strong_wind_hold_daily_events: 1列 (bool)
        reset=True 时会重置到第一行
        """
        if reset:
            self._lhs_iter = self._init_lhs_iterator()

        try:
            row = next(self._lhs_iter)
        except StopIteration:
            # 如果读到文件结尾，重新初始化迭代器
            self._lhs_iter = self._init_lhs_iterator()
            row = next(self._lhs_iter)

        # 列转换
        smp_durations = [float(x) for x in row[0:18]]
        smp_delivery_delay_days = [float(x) for x in row[18:36]]
        smp_crane_failure_times = _parse_float_list(row[36])
        smp_rain_hold_daily_events = _parse_bool_list(row[37])
        smp_strong_wind_hold_daily_events = _parse_bool_list(row[38])

        return (
            smp_durations,
            smp_delivery_delay_days,
            smp_crane_failure_times,
            smp_rain_hold_daily_events,
            smp_strong_wind_hold_daily_events,
        )



    def get_sf_erection_durations(self):
        """
        获取18个楼层的数据（每个文件取下一行）

        :return: 包含18个数据的列表，按楼层1-18顺序排列
        """
        result = []
        for floor in range(1, 19):
            try:
                result.append(next(self.file_readers[floor]))
            except StopIteration:
                # 如果文件已读完，重新初始化读取器
                filename = f'flr{floor:02d}_samples.csv'
                # filepath = os.path.join(self.samples_dir, filename)
                filepath = Path(self.samples_dir) / filename  # 如果self.samples_dir可能是字符串

                self.file_readers[floor] = pd.read_csv(filepath)['value'].iteritems()
                result.append(next(self.file_readers[floor]))

        return result
    def get_component_delivery_delays(self):
        """Generate component delivery delays."""
        return self._rng.normal(
            Constants.COMPONENT_DELIVERY_DELAY_LOC,
            Constants.COMPONENT_DELIVERY_DELAY_SCALE,
            self.n_sf
        )
    #
    # def get_sf_erection_durations(self):
    #     """Generate floor erection durations with special cases."""
    #     durations = np.empty(self.n_sf)
    #
    #     # First two floors (+1 offset)
    #     durations[:2] = self._generate_standard_duration(size=2, offset=1)
    #
    #     # Middle floors
    #     if self.n_sf > 3:
    #         durations[2:-1] = self._generate_standard_duration(size=self.n_sf - 3)
    #
    #     # Top floor (+1 offset)
    #     if self.n_sf >= 3:
    #         durations[-1] = self._generate_standard_duration(offset=1)
    #
    #     return durations

    # def get_standard_duration(self, size=1):
    #     """Public method to get standard duration only."""
    #     return self._generate_standard_duration(size=size)

# if __name__ == "__main__":
    # # random_util = RandomUtil(seed=3, n_sf=Constants.N_ACTIVITY)
    # current_dir = Path(__file__)
    # samples_dir = current_dir.parent.parent / "sampling" / "samples"
    # random_util = RandomUtil(seed = 3, n_sf= Constants.N_ACTIVITY, samples_dir=samples_dir)
    # print()
    # print(random_util.get_sf_erection_durations())
    # print(random_util.get_sf_erection_durations())
    # print(random_util.get_sf_erection_durations())
    # print(random_util.get_sf_erection_durations())
    # print("exit")
    # exit()
    # # Define the CSV filename
    # filename = 'act_delivery_delay.csv'


    # # Open the CSV file for writing
    # with open(filename, mode='w', newline='') as file:
    #     writer = csv.writer(file)
    #
    #     # Write the header
    #     header = ['seed']
    #     for i in range(1, Constants.N_ACTIVITY + 1):
    #         header.append(f'FLR{i:02d}')
    #     writer.writerow(header)
    #
    #     # Generate and write data for each seed
    #     for seed in range(1, 21):
    #         random_util._rng = np.random.default_rng(seed)  # Update the seed
    #         act_delivery_delay = [seed]
    #         act_delivery_delay.extend(random_util.get_component_delivery_delays())
    #         act_delivery_delay = [' ' if x < 0 else ceil(x) for x in act_delivery_delay]
    #         writer.writerow(act_delivery_delay)
    #
    # print(f"Data has been written to {filename}")


def main():
    """测试 get_samples 方法"""
    ru = RandomUtil(samples_dir=".\..\sampling\lhs")
    print("第一次调用:")
    # print(ru.get_samples())

    (smp_durations,
     smp_delivery_delay_days,
     smp_crane_failure_times,
     smp_rain_hold_daily_events,
     smp_strong_wind_hold_daily_events) = ru.get_samples()
    print(smp_durations)
    print(smp_delivery_delay_days)
    print(smp_crane_failure_times)
    print(smp_rain_hold_daily_events)
    print(smp_strong_wind_hold_daily_events)

    print("\n第二次调用:")
    print(ru.get_samples())

    PROJECT_ROOT = Path(__file__).resolve().parents[1]
    print(PROJECT_ROOT.__str__())
    csv_file = PROJECT_ROOT / "data" / "lhs_sampling_results.csv"
    print(csv_file.__str__())
    # print("\nreset=True 重新开始:")
    # print(ru.get_samples(reset=True))


if __name__ == "__main__":
    main()
